package spbun.fileclean.anaylize;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import spbun.fileclean.common.FileUtil;
import spbun.fileclean.dto.CompareResult;
import spbun.fileclean.dto.FileInfo;

/**
 * 文件分析<br>
 * 我们提供了两类，文件夹对比以及文件的对比
 * 
 * @author NOLYDAKE
 *
 */
public class FileAnaylize {

	/** 日志 */
	private static final Logger LOG = Logger.getLogger(FileAnaylize.class);

	private static String getParent(String path) {
		return path.substring(0, path.lastIndexOf("\\"));
	}

	public static void main(String[] args) {

		List<FileInfo> list1 = new ArrayList<>();
		{
			FileInfo fi = new FileInfo();
			fi.setPath("c:\\a\\1.txt");
			fi.setName("1.txt");
			fi.setSize(500);
			list1.add(fi);
		}
		{
			FileInfo fi = new FileInfo();
			fi.setPath("c:\\b\\1.txt");
			fi.setName("1.txt");
			fi.setSize(500);
			list1.add(fi);
		}
		{
			FileInfo fi = new FileInfo();
			fi.setPath("c:\\b\\2.txt");
			fi.setName("2.txt");
			fi.setSize(500);
			list1.add(fi);
		}

		// List<CompareResult> crs = new ArrayList<>();

		FileAnaylize fa = new FileAnaylize(list1);

		fa.forderLike();
	}

	/**
	 * 原始文件列表
	 */
	private List<FileInfo> fileList = null;

	Map<List<FileInfo>, Map<String, FileInfo>> cache = new HashMap<>();

	public FileAnaylize(List<FileInfo> fileList) {
		super();
		this.fileList = fileList;
	}

	/**
	 * 判断两个目录是否相同
	 */
	public void bigSameFile() {

		long start = System.currentTimeMillis();

		int same = 0;

		int size = 1024 * 1024 * 500;// 列出所有大于500M的文件

		for (FileInfo fi1 : fileList) {

			if (fi1.getSize() < size) {
				continue;
			}

			LOG.info("====");
			LOG.info(FileUtil.getFileSize(fi1.getSize()));
			LOG.info(fi1.getPath());
		}

		long end = System.currentTimeMillis();

		LOG.debug("大文件数量:" + same);
		LOG.debug("大文件循环耗时:" + (end - start) / 1000 + "秒");
	}

	private int caculateBE(List<FileInfo> list1, List<FileInfo> list2) {

		int same = 0;

		int size = list2.size();

		Map<String, FileInfo> map = conventFileInfos2Map(list2);

		for (FileInfo fileInfo : list1) {

			if (map.containsKey(makeKey(fileInfo))) {
				same++;
			}
		}

		return same * 100 / size;

	}

	private void compare(List<FileInfo> list1, List<FileInfo> list2, List<CompareResult> crs) {

		if (list1 == list2) {// 如果对象相同，我们不比较，因为100%相同，呵呵。
			return;
		}

		// 判断是否比较
		// 如果要判断的目录为空，我们不统计
		if (list1 == null || list1.size() == 0 || list2 == null || list2.size() == 0) {
			return;
		}

		String before = getParent(list1.get(0).getPath());
		String end = getParent(list2.get(0).getPath());

		if (before.equals("D:\\GR\\windows\\Desktop\\网盘要上传\\Photo.照片\\照片\\相片\\大学\\大学同学")
				&& end.equals("D:\\GR\\windows\\Desktop\\网盘要上传\\Photo.照片\\照片\\相片")) {
			System.out.println(12354);
		}

		CompareResult cr = new CompareResult(before, end);
		if (crs.contains(cr)) {// 统计过，就不再统计
			return;
		}

		// 开始进行比较

		// 看看before与end的比较
		cr.setPercentBE(caculateBE(list1, list2));

		// 看看end与before的比较
		cr.setPercentEB(caculateBE(list2, list1));

		if (cr.getPercent() == 0) {
			return;
		}

		crs.add(cr);
	}

	private Map<String, FileInfo> conventFileInfos2Map(List<FileInfo> list) {

		Map<String, FileInfo> map = cache.get(list);

		if (map != null) {
			return map;
		}

		map = new HashMap<>();

		for (FileInfo fileInfo : list) {
			map.put(makeKey(fileInfo), fileInfo);
		}

		return map;
	}

	private Map<String, List<FileInfo>> convnet2Map() {

		long start = System.currentTimeMillis();

		Map<String, List<FileInfo>> forders = new HashMap<>();

		for (FileInfo fileInfo : fileList) {

			String parentPath = getParent(fileInfo.getPath());

			List<FileInfo> infos = forders.get(parentPath);
			if (infos == null) {
				infos = new ArrayList<>();
				forders.put(parentPath, infos);
			}

			infos.add(fileInfo);
		}

		long end = System.currentTimeMillis();

		LOG.info("解析文件耗时：" + (end - start));

		LOG.info("目录总数：" + forders.size());

		return forders;
	}

	/**
	 * 判断两个目录是否相同
	 */
	public void fileLike() {

		long start = System.currentTimeMillis();

		int same = 0;

		int mixSize = 1024 * 1024 * 50;

		HashMap<String, FileInfo> set = new HashMap<>();

		for (FileInfo fi1 : fileList) {

			if (fi1.getSize() < mixSize) {
				continue;
			}

			String key = makeKey(fi1);

			if (set.containsKey(key)) {

				LOG.info("====");
				LOG.info(FileUtil.getFileSize(fi1.getSize()));
				LOG.info(set.get(key).getPath());
				LOG.info(fi1.getPath());

				same++;
			} else {
				set.put(key, fi1);
			}
		}

		long end = System.currentTimeMillis();

		LOG.debug("重复文件数量:" + same);
		LOG.debug("文件循环比较耗时:" + (end - start) / 1000 + "秒");
	}

	/**
	 * 判断两个目录是否相同
	 */
	public void forderLike() {

		long start = System.currentTimeMillis();

		Map<String, List<FileInfo>> forders = convnet2Map();

		Collection<List<FileInfo>> values = forders.values();

		List<CompareResult> crs = new ArrayList<>();

		for (List<FileInfo> list1 : values) {
			for (List<FileInfo> list2 : values) {
				compare(list1, list2, crs);
			}
		}

		long end = System.currentTimeMillis();

		Collections.sort(crs, new Comparator<CompareResult>() {

			@Override
			public int compare(CompareResult o1, CompareResult o2) {
				return o2.getPercent() - o1.getPercent();
			}
		});

		LOG.info("目录比较耗时:" + (end - start) / 1000 + "秒");
		LOG.info(crs);
	}

	Map<FileInfo, String> keyCache = new HashMap<>();

	private String makeKey(FileInfo fileInfo) {

		String key = keyCache.get(fileInfo);
		if (key != null) {
			return key;
		}

		key = fileInfo.getName() + "|" + fileInfo.getSize();
		keyCache.put(fileInfo, key);

		return key;
	}
}
